package com.whfc.fuum.service.impl;

import com.whfc.common.enums.SysRulePlatform;
import com.whfc.common.enums.SysUserType;
import com.whfc.common.exception.BizException;
import com.whfc.common.result.ResultEnum;
import com.whfc.fuum.dao.*;
import com.whfc.fuum.dto.SysRuleDTO;
import com.whfc.fuum.dto.SysUserDTO;
import com.whfc.fuum.entity.SysExternalLink;
import com.whfc.fuum.entity.SysRule;
import com.whfc.fuum.entity.SysUser;
import com.whfc.fuum.enums.PageType;
import com.whfc.fuum.param.SysRuleAdd;
import com.whfc.fuum.param.SysRuleEdit;
import com.whfc.fuum.redis.SysUserRedisDao;
import com.whfc.fuum.service.SysRuleService;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description:
 * @author: xugcheng
 * @version: 1.0
 * @date: 2019/7/23 20:57
 */
@DubboService(interfaceClass = SysRuleService.class, version = "1.0.0")
public class SysRuleServiceImpl implements SysRuleService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SysRuleMapper ruleMapper;

    @Autowired
    private SysRoleRuleMapper roleRuleMapper;

    @Autowired
    private SysRoleRuleMapper sysRoleRuleMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysUserRedisDao sysUserRedisDao;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysExternalLinkMapper sysExternalLinkMapper;

    @Override
    public List<SysRuleDTO> getRuleList(SysUser user, Integer platform) {
        SysRulePlatform rulePlatform = SysRulePlatform.parseValue(platform);
        if (rulePlatform == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "权限平台类型错误.");
        }
        if (SysUserType.INNER.getValue().equals(user.getType())) {
            return ruleMapper.selectAllRuleList(platform);
        } else {
            return ruleMapper.selectUserAllRuleList(user.getId(), platform);
        }
    }

    @Override
    public List<SysRuleDTO> getDescendantList(Integer pid) {
        return ruleMapper.selectDescendantRuleList(pid);
    }

    @Override
    public void addRule(SysRuleAdd param) {

        Integer ruleId = param.getRuleId();
        String code = param.getCode();
        String path = param.getPath();
        Integer platform = param.getPlatform();
        Integer pageType = param.getPageType();
        SysRulePlatform rulePlatform = SysRulePlatform.parseValue(platform);
        if (rulePlatform == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "权限平台不存在");
        }

        //验证code
        if (!StringUtils.isEmpty(code)) {
            SysRule rule = ruleMapper.selectByCode(code, platform);
            if (rule != null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "权限编码重复");
            }
        }
        //验证path
        if (!StringUtils.isEmpty(path)) {
            SysRule rule = ruleMapper.selectByPath(path, platform);
            if (rule != null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "访问路径重复");
            }
        }

        //外链处理
        if (PageType.outer.getValue().equals(pageType)) {
            Integer deptId = 0;
            SysExternalLink link = new SysExternalLink();
            link.setDeptId(deptId);
            link.setCode(code);
            link.setUrl(path);
            sysExternalLinkMapper.insertSelective(link);
//            path = "";
        }

        //新增权限信息
        SysRule rule = new SysRule();
        rule.setId(ruleId);
        rule.setName(param.getRuleName());
        rule.setShortName(param.getShortName());
        rule.setCode(code);
        rule.setPath(path);
        rule.setType(param.getType());
        rule.setPid(param.getPid());
        rule.setIndex(param.getIndex());
        rule.setIconPath(param.getIconPath());
        rule.setPlatform(platform);
        rule.setPageType(pageType);
        rule.setContent(param.getContent());
        rule.setIconUnselect(param.getIconUnselect());
        rule.setSupervise(param.getSupervise());
        rule.setAppScene(param.getAppScene());
        ruleMapper.insertSelective(rule);
        //清理内部账号权限
        clearInnerRuleCache();
        //清理内部账号权限
        clearInnerRuleCache();
    }

    @Override
    public void editRule(SysRuleEdit param) {
        Integer ruleId = param.getRuleId();
        Integer pageType = param.getPageType();
        SysRule rule = ruleMapper.selectByPrimaryKey(ruleId);
        if (rule == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该权限不存在");
        }
        //验证权限平台
        Integer platform = param.getPlatform();
        SysRulePlatform rulePlatform = SysRulePlatform.parseValue(platform);
        if (rulePlatform == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "权限平台不存在");
        }
        //验证code
        String code = param.getCode();
        if (!StringUtils.isEmpty(code)) {
            SysRule sysRule = ruleMapper.selectByCode(code, platform);
            if (sysRule != null && !sysRule.getId().equals(ruleId)) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "权限编码重复");
            }
        }
        //验证path
        String path = param.getPath();
        if (!StringUtils.isEmpty(path)) {
            SysRule sysRule = ruleMapper.selectByPath(path, platform);
            if (sysRule != null && !sysRule.getId().equals(ruleId)) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "访问路径重复");
            }
        }

        //外链处理
        if (PageType.outer.getValue().equals(pageType)) {
            Integer deptId = 0;
            SysExternalLink link = new SysExternalLink();
            link.setDeptId(0);
            link.setCode(code);
            link.setUrl(path);
            int count = sysExternalLinkMapper.countByDeptIdAndCode(deptId, code);
            if (count > 0) {
                sysExternalLinkMapper.updateByPrimaryKeySelective(link);
            } else {
                sysExternalLinkMapper.insertSelective(link);
            }
//            path = "";
        }

        //更新权限信息
        rule.setName(param.getRuleName());
        rule.setShortName(param.getShortName());
        rule.setCode(code);
        rule.setPath(path);
        rule.setType(param.getType());
        rule.setIndex(param.getIndex());
        rule.setIconPath(param.getIconPath());
        rule.setIconUnselect(param.getIconUnselect());
        rule.setSupervise(param.getSupervise());
        rule.setAppScene(param.getAppScene());
        rule.setPageType(pageType);
        rule.setPlatform(platform);
        rule.setContent(param.getContent());
        //rule.setPid(param.getPid());
        ruleMapper.updateByPrimaryKeySelective(rule);

        //删除相关用户的权限缓存
        clearRuleCache(ruleId);
        //清理内部账号权限
        clearInnerRuleCache();
    }


    @Override
    public void enableRule(Integer ruleId) {
        ruleMapper.enableRule(ruleId);
    }

    @Override
    public void disableRule(Integer ruleId) {
        ruleMapper.disableRule(ruleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delRule(Integer ruleId) {

        int childCnt = ruleMapper.countByPid(ruleId);
        if (childCnt > 0) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该节点拥有子节点,不能删除");
        }

        //删除相关用户的权限缓存
        clearRuleCache(ruleId);
        //清理内部账号权限
        clearInnerRuleCache();

        //删除权限
        ruleMapper.logicDeleteById(ruleId);
        roleRuleMapper.deleteByRuleId(ruleId);
    }

    @Override
    public List<Integer> getRoleIdsByRuleCode(String ruleCode) throws BizException {
        return roleRuleMapper.selectRoleIdsByRuleCode(ruleCode);
    }

    /**
     * 清理用户权限缓存
     *
     * @param ruleId 权限ID
     */
    private void clearRuleCache(Integer ruleId) {
        List<Integer> roleIdList = sysRoleRuleMapper.selectRoleIdsByRuleId(ruleId);
        if (roleIdList.isEmpty()) {
            return;
        }
        List<Integer> userIds = sysUserRoleMapper.selectUserIdByRoleIds(roleIdList);
        if (userIds.isEmpty()) {
            return;
        }
        sysUserRedisDao.deleteUserRules(userIds);
    }

    /**
     * 清理内部账号的权限缓存
     */
    private void clearInnerRuleCache() {
        //清理内部账号的权限缓存
        List<SysUserDTO> list = sysUserMapper.selectInnerUsers(null);
        List<Integer> userIdList = list.stream().map(SysUserDTO::getId).collect(Collectors.toList());
        sysUserRedisDao.deleteUserRules(userIdList);
    }
}
